﻿using System;
using Microsoft.Win32;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Xml;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using DistrRTgen;

namespace rtgen_guiclient
{
    /*  
      public delegate void myCallback(string sData);
      delegate int SetTextCallback(string text);
      delegate void SetProgressCallback();
      delegate void SetProgressCallbackParam(int nProgress);
      public delegate void SetStatusCallback(string sStatus);
      delegate void SetTextCallbackLine(string sData, int line);
      delegate void UpdateWUStatusCallback(string sName, string sStatus);
      delegate void SetAddWUCallback(ListViewItem item);
      delegate void AddHashCallBack(CHash oHash);
      delegate ListViewItem[] SearchWUListCallback(string sSearch, bool bSearchSub);
      delegate ListViewItem GetNSWUCallback();
      delegate ListViewItem GetWUCallback(int nPosition);
      delegate ListView.ListViewItemCollection GetListViewCallback();
      //public delegate void UpdateCrackingProgressCallback(String sHash, String sTableset, String sProgress);
  */
    public partial class MainForm : Form
    {
        /*public string sDataPath = Path.Combine(
                                            Environment.GetFolderPath(
                                            Environment.SpecialFolder.ApplicationData),
                                        Application.CompanyName) + "\\";
        private const int WM_VSCROLL = 0x115;
        private const int SB_BOTTOM = 7;*/
        public LoggerLevel LogThreshold;
        static public MainForm myRef;
        /*[DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);*/
        private Logger log;
        private ChainGenerator CG;
        private ComputerList _MachineList;
        private uint _LastEventID;
        private ListViewColumnSorter lvwColumnSorter;

        public MainForm()
        {
            /*
            Dictionary<string, Object> props = new Dictionary<string, Object>();
            props.Clear();
            props["name"] = "tcp";
            props["protectionLevel"] = System.Net.Security.ProtectionLevel.EncryptAndSign; 
            props["secure"] = true;
            props["domain"] = "dpunet";
            props["username"] = "mwjadmin";
            props["password"] = "L0v1nNY";
            TcpClientChannel tcp = new TcpClientChannel(props, new BinaryClientFormatterSinkProvider());
            ChannelServices.UnregisterChannel(ChannelServices.RegisteredChannels[0]);
            ChannelServices.RegisterChannel(tcp, true);
             */
            InitializeComponent();
           // Environment.CurrentDirectory = Application.CommonAppDataPath;

            myRef = this;
            LogThreshold = LoggerLevel.LOG_INFO;
            lvwColumnSorter = new ListViewColumnSorter();
            this.lvRemoteEventLog.ListViewItemSorter = lvwColumnSorter;
            this.lvLocalEventLog.ListViewItemSorter = lvwColumnSorter;
            this.lvRemoteParts.ListViewItemSorter = lvwColumnSorter;
            this.lvComputerList.ListViewItemSorter = lvwColumnSorter;
            _MachineList = new ComputerList(lvComputerList);
            UpdateLocalView(false);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Distributed Rainbowtables Generator v4.00\n\nMade by Martin Westergaard\nEmail me at martinwj2005@gmail.com\n\nVisit freerainbowtables.com to download the completed tables\n\nThanks to Zhu Shuanglei (http://www.antsight.com/zsl/rainbowcrack/) for the making of Rainbowcrack!\nThanks to Massimiliano Montoro (http://www.oxid.it/) for providing the algorithms for mscache, lmchall, halflmchall, ntlmchall and oracle", "Distributed Rainbowtables Generator");
        }





        private class ClientInfo
        {
            public LoggedEvent[] Events;
            public string Username;
            public string Password;
            public long Speed;
            public List<WorkUnit> WUList;
            public int MaxProcessorsToUse;
            public int NumProcessors;
            public string Version;
            public DateTime UploadStart;
            public DateTime UploadEnd;
            public bool UploadParts;
            public bool AcceptNewParts;
            public LoggerLevel EventLogThreshold;
            public DateTime WorkStart;
            public DateTime WorkEnd;
            public bool EnablePublicHashCracking;
        }
        private ClientInfo FetchClientInfo(Computer Machine, uint MinEventID)
        {
            try
            {
                ClientInfo info = new ClientInfo();
                Dictionary<string, Object> props = new Dictionary<string, Object>();
                props.Clear();
                props["name"] = "tcp";
                props["protectionLevel"] = System.Net.Security.ProtectionLevel.EncryptAndSign;
                props["secure"] = true;
                props["domain"] = Machine.Credentials.Domain;
                props["username"] = Machine.Credentials.Username;
                props["password"] = Machine.Credentials.Password;
                TcpClientChannel tcp = new TcpClientChannel(props, new BinaryClientFormatterSinkProvider());
                if(ChannelServices.RegisteredChannels.Length > 0)
                    ChannelServices.UnregisterChannel(ChannelServices.RegisteredChannels[0]);
                ChannelServices.RegisterChannel(tcp, true);
                log = (Logger)Activator.GetObject(typeof(Logger), "tcp://" + Machine.Hostname + ":36433/log");
                info.Events = log.GetLastEntries(LogThreshold, MinEventID);
                Server s = (Server)Activator.GetObject(typeof(Server), "tcp://" + Machine.Hostname + ":36433/distrrtgen");
                CG = s.Instance;
                // Fetch username / password
                info.Username = CG.Username;
                info.Password = CG.Password;
                info.MaxProcessorsToUse = CG.MaxProcessorsToUse;
                info.NumProcessors = CG.NumProcessors;
                // Fetch speed
                info.Speed = CG.CurrentSpeed;
                info.Version = CG.Version;
                // Fetch work queue
                info.WUList = CG.WUList.WorkUnits;
                info.UploadEnd = CG.UploadEndTime;
                info.UploadStart = CG.UploadStartTime;
                info.AcceptNewParts = CG.AcceptNewParts;
                info.UploadParts = CG.UploadParts;
                info.EventLogThreshold = CG.EventLogThreshold;
                info.WorkStart = CG.WorkStartTime;
                info.WorkEnd = CG.WorkEndTime;
                info.EnablePublicHashCracking = CG.EnablePublicHashCracking;

                return info;
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Could not connect to " + Machine.Hostname + ": " + ex.Message);                
            }
            return null;
        }
        private void UpdateRemoteView()
        {
            lvRemoteEventLog.Items.Clear();
            lvRemoteParts.Items.Clear();
            int num = lvComputerList.SelectedItems.Count;
            string Username = "[blank]";
            string Password = "[blank]";
            string UploadStart = "[blank]";
            string UploadEnd = "[blank]";
            string WorkStart = "[blank]";
            string WorkEnd = "[blank]";
            bool evtThresholdSet = false;
            bool evtThresholdMixed = false;
            LoggerLevel evtThreshold = LoggerLevel.LOG_INFO;
            int AcceptParts = 4;
            int UploadParts = 4;
            int PublicHashCracking = 4;
            ChainGenerator _RemoteCG = null;
            Logger _RemoteLog = null;

            for (int i = 0; i < num; i++)
            {
                Computer Machine = _MachineList.Get(lvComputerList.SelectedItems[i].SubItems[0].Text);
                Dictionary<string, Object> props = new Dictionary<string, Object>();
                props.Clear();
                props["name"] = "tcp";
                props["protectionLevel"] = System.Net.Security.ProtectionLevel.EncryptAndSign;
                props["secure"] = true;
                props["domain"] = Machine.Credentials.Domain;
                props["username"] = Machine.Credentials.Username;
                props["password"] = Machine.Credentials.Password;
                try
                {
                    TcpClientChannel tcp = new TcpClientChannel(props, new BinaryClientFormatterSinkProvider());
                    ChannelServices.UnregisterChannel(ChannelServices.RegisteredChannels[0]);
                    ChannelServices.RegisterChannel(tcp, true);
                    _RemoteLog = (Logger)Activator.GetObject(typeof(Logger), "tcp://" + Machine.Hostname + ":36433/log");
                    Server s = (Server)Activator.GetObject(typeof(Server), "tcp://" + Machine.Hostname + ":36433/distrrtgen");
                    _RemoteCG = s.Instance;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not connect to " + Machine.Hostname + ": " + ex.Message);
                    continue;
                }
//                if (_RemoteCG == null ||_RemoteLog == null)
  //                  continue;
                _MachineList.SetVersion(Machine, _RemoteCG.Version);
                // Go through the event log
                LoggedEvent[] Events = _RemoteLog.GetLastEntries(GetLoggerLevelFromIndex(cbRemoteEventFilter.SelectedIndex));

                for (int j = Events.Length - 1; j >= 0; j--)
                {
                    if (Events[j] != null)
                    {
                        lvRemoteEventLog.Items.Insert(0, new ListViewItem(new string[] { Logger.GetLevelString(Events[j].Level), _RemoteCG.Hostname, Events[j].Time.ToString(), Events[j].Event }));
                    }
                }

                // Parts set
                for (int j = 0; j < _RemoteCG.WUList.Count; j++)
                {
                    WorkUnit WU = _RemoteCG.WUList[j];
                    string Progress = "Not started";
                    if (WU.InUse == true)
                    {
                        for (int k = 0; k < _RemoteCG.WorkThreads.Length; k++)
                        {
                            if (_RemoteCG.WorkThreads[k] != null && _RemoteCG.WorkThreads[k].GetType() == typeof(WUProcess))
                            {
                                WUProcess proc = (WUProcess)_RemoteCG.WorkThreads[k];
                                if (proc.PartID == WU.PartID)
                                {
                                    Progress = proc.GetPercentDone().ToString() + "%";
                                }
                            }
                        }
                    }
                    lvRemoteParts.Items.Add(new ListViewItem(new string[] { _RemoteCG.Hostname, WU.HashRoutine + "_" + WU.Charset + "#" + WU.MinLetters + "-" + WU.MaxLetters + "_" + WU.Index + "_" + WU.ChainLength + "x" + WU.ChainCount + " " + WU.PartID, Progress }));
                }


                // Event Threshold checking
                if (evtThresholdSet == false)
                    evtThreshold = _RemoteCG.EventLogThreshold;
                else if (evtThreshold != _RemoteCG.EventLogThreshold)
                    evtThresholdMixed = true;

                // Username checking
                if (Username == "[blank]")
                {
                    Username = _RemoteCG.Username;
                }
                else if (_RemoteCG.Username != Username)
                {
                    Username = "[mixed]";
                }


                // Password checking
                if (Password == "[blank]")
                    Password = _RemoteCG.Password;
                else if (_RemoteCG.Password != Password)
                    Password = ""; // If we have different passwords, then blank it

                // Upload start and end
                if (UploadStart == "[blank]")
                    UploadStart = _RemoteCG.UploadStartTime.TimeOfDay.ToString();
                else if (UploadStart != _RemoteCG.UploadStartTime.TimeOfDay.ToString())
                    UploadStart = "";
                if (UploadEnd == "[blank]")
                    UploadEnd = _RemoteCG.UploadEndTime.TimeOfDay.ToString();
                else if (UploadEnd != _RemoteCG.UploadEndTime.TimeOfDay.ToString())
                    UploadEnd = "";

                // Work time schedule
                if (WorkStart == "[blank]")
                    WorkStart = _RemoteCG.WorkStartTime.TimeOfDay.ToString();
                else if (WorkStart != _RemoteCG.WorkStartTime.TimeOfDay.ToString())
                    WorkStart = "";
                if (WorkEnd == "[blank]")
                    WorkEnd = _RemoteCG.WorkEndTime.TimeOfDay.ToString();
                else if (WorkEnd != _RemoteCG.WorkEndTime.TimeOfDay.ToString())
                    WorkEnd = "";

                if (UploadParts == 4)
                    UploadParts = Convert.ToInt32(_RemoteCG.UploadParts);
                else if (UploadParts != Convert.ToInt32(_RemoteCG.UploadParts))
                    UploadParts = 2;

                if (AcceptParts == 4)
                    AcceptParts = Convert.ToInt32(_RemoteCG.AcceptNewParts);
                else if (AcceptParts != Convert.ToInt32(_RemoteCG.AcceptNewParts))
                    AcceptParts = 2;

                if (PublicHashCracking == 4)
                    PublicHashCracking = Convert.ToInt32(_RemoteCG.EnablePublicHashCracking);
                else if (PublicHashCracking != Convert.ToInt32(_RemoteCG.EnablePublicHashCracking))
                    PublicHashCracking = 2;
                if (num > 1)
                {
                    txtRemoteMaxCPU.Enabled = false;
                }
                else
                {
                    txtRemoteMaxCPU.Enabled = true;
                    txtRemoteMaxCPU.Maximum = _RemoteCG.NumProcessors;
                    txtRemoteMaxCPU.Value = _RemoteCG.MaxProcessorsToUse;
                }
            }
            if (_RemoteCG == null || _RemoteLog == null)
                return;
            txtRemoteUsername.Text = Username;
            txtRemotePassword.Text = Password;
            txtRemoteUploadStart.Text = UploadStart;
            txtRemoteUploadEnd.Text = UploadEnd;
            txtRemoteWorkStart.Text = WorkStart;
            txtRemoteWorkEnd.Text = WorkEnd;

            cbRemoteAcceptParts.CheckState = (CheckState)AcceptParts;
            cbRemoteUploadParts.CheckState = (CheckState)UploadParts;
            cbRemotePublicHashCracking.CheckState = (CheckState)PublicHashCracking;

            if (evtThresholdMixed)
            {
                cbRemoteEventThreshold.SelectedIndex = -1;
            }
            else
            {
                switch (evtThreshold)
                {
                    case LoggerLevel.LOG_DEBUG:
                        cbRemoteEventThreshold.SelectedIndex = 0;
                        break;
                    case LoggerLevel.LOG_INFO:
                        cbRemoteEventThreshold.SelectedIndex = 1;
                        break;
                    case LoggerLevel.LOG_ALERT:
                        cbRemoteEventThreshold.SelectedIndex = 2;
                        break;
                    case LoggerLevel.LOG_ERROR:
                        cbRemoteEventThreshold.SelectedIndex = 3;
                        break;
                }

            }

        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            /*
            if (lvComputerList.SelectedItems.Count == 1)
            {

                Server s = (Server)Activator.GetObject(typeof(Server), "tcp://" + lvComputerList.SelectedItems[0].Text + ":8888/distrrtgen");
                CG = s.Instance;
                CG.Username = txtUsername.Text;
                CG.Password = txtPassword.Text;
                CG.MaxProcessorsToUse = (int)MaxProcsToUse.Value;
                CG.AcceptNewParts = cbAcceptNew.Checked;
                CG.UploadParts = cbUpload.Checked;
                try
                {
                    DateTime Start = Convert.ToDateTime(txtUploadStart.Text);
                    CG.UploadStartTime = Start;
                }
                catch
                {
                    MessageBox.Show("Invalid time format in Upload Start");
                }
                try
                {
                    DateTime End = Convert.ToDateTime(txtUploadEnd.Text);
                    CG.UploadEndTime = End;
                }
                catch
                {
                    MessageBox.Show("Invalid time format in Upload End");
                }
                LoggerLevel lvl = GetLoggerLevelFromIndex(lbEventThreshold.SelectedIndex);
//                CG.EventLogThreshold = lvl;
            }*/
        }
        private LoggerLevel GetLoggerLevelFromIndex(int Index)
        {
            switch (Index)
            {
                case 0:
                    return LoggerLevel.LOG_DEBUG;
                case 1:
                    return LoggerLevel.LOG_INFO;
                case 2:
                    return LoggerLevel.LOG_ALERT;
                case 3:
                    return LoggerLevel.LOG_ERROR;
            }
            return LoggerLevel.LOG_INFO;
        }
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            LogThreshold = GetLoggerLevelFromIndex(cbRemoteEventFilter.SelectedIndex);
            UpdateRemoteView();
        }

        private void lvComputerList_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                if (lvComputerList.SelectedItems.Count > 0)
                {
                    ComputerRightClickMenu.Show(Cursor.Position);
                }
            }
        }

        private void ComputerRightClickMenu_Delete_Click(object sender, EventArgs e)
        {
            ListView.SelectedListViewItemCollection items = lvComputerList.SelectedItems;
            while (lvComputerList.SelectedItems.Count > 0)
            {
                _MachineList.Remove(lvComputerList.SelectedItems[0].Text);
            }
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            UpdateRemoteView();
        }

        private void lvComputerList_SelectedIndexChanged(object sender, EventArgs e)
        {
            timerLocal.Stop();
        }

        private void deployServiceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MSIDeploy msi = new MSIDeploy();
            msi.ShowDialog();
        }

        private void UpdateLocalView(bool SkipSettings)
        {
            ClientInfo info = FetchClientInfo(new Computer("localhost"), _LastEventID + 1);
            if (info == null)
            {
                timerLocal.Enabled = false;
                return;
            }
            if (SkipSettings == false)
            {
                txtLocalUsername.Text = info.Username;
                txtLocalPassword.Text = info.Password;
                LocalMaxProcsToUse.Value = info.MaxProcessorsToUse;
                LocalMaxProcsToUse.Maximum = info.NumProcessors;
                cbLocalAcceptNew.Checked = info.AcceptNewParts;
                cbLocalUpload.Checked = info.UploadParts;
                txtLocalUploadStart.Text = Convert.ToString(info.UploadStart.TimeOfDay);
                txtLocalUploadEnd.Text = Convert.ToString(info.UploadEnd.TimeOfDay);
                cbLocalEnablePublicHashCracking.Checked = info.EnablePublicHashCracking;
                txtLocalWorkStart.Text = Convert.ToString(info.WorkStart.TimeOfDay);
                txtLocalWorkEnd.Text = Convert.ToString(info.WorkEnd.TimeOfDay);
                switch (info.EventLogThreshold)
                {
                    case LoggerLevel.LOG_DEBUG:
                        evtLogThreshold.SelectedIndex = 0;
                        break;
                    case LoggerLevel.LOG_INFO:
                        evtLogThreshold.SelectedIndex = 1;
                        break;
                    case LoggerLevel.LOG_ALERT:
                        evtLogThreshold.SelectedIndex = 2;
                        break;
                    case LoggerLevel.LOG_ERROR:
                        evtLogThreshold.SelectedIndex = 3;
                        break;
                }
            }
            lblLocalSpeed.Text = info.Speed.ToString();
            for (int i = info.Events.Length - 1; i >= 0; i--)
            {
                if (info.Events[i] == null)
                    continue;
                lvLocalEventLog.Items.Insert(0, new ListViewItem(new string[] { Logger.GetLevelString(info.Events[i].Level), info.Events[i].Time.ToString(), info.Events[i].Event }));
            }
            if (info.Events.Length > 0 && info.Events[0] != null)
                _LastEventID = info.Events[0].EventID;

            lvLocalWUList.Items.Clear();
            for (int i = 0; i < info.WUList.Count; i++)
            {
                WorkUnit WU = info.WUList[i];
                string Progress = "Not started";
                if (WU.InUse == true)
                {
                    for (int j = 0; j < CG.WorkThreads.Length; j++)
                    {
                        if (CG.WorkThreads[j] != null && CG.WorkThreads[j].GetType() == typeof(WUProcess))
                        {
                            WUProcess proc = (WUProcess)CG.WorkThreads[j];
                            if (proc.PartID == WU.PartID)
                            {
                                Progress = proc.GetPercentDone().ToString() + "%";
                            }
                        }
                    }
                }
                else if (WU.Uploading == true)
                {
                    Progress = "Uploading " + WU.PercentUploaded + "%";
                }
                lvLocalWUList.Items.Add(new ListViewItem(new string[] { WU.HashRoutine + "_" + WU.Charset + "#" + WU.MinLetters + "-" + WU.MaxLetters + "_" + WU.Index + "_" + WU.ChainLength + "x" + WU.ChainCount + " " + WU.PartID, Progress }));
            }
        }
        private void timerLocal_Tick(object sender, EventArgs e)
        {
            UpdateLocalView(true);
        }

        private void cbLocalFilter_SelectedIndexChanged(object sender, EventArgs e)
        {
            LogThreshold = GetLoggerLevelFromIndex(cbLocalFilter.SelectedIndex);
            _LastEventID = 0;
            lvLocalEventLog.Items.Clear();
            UpdateLocalView(true);
        }

        private void btnLocalSave_Click(object sender, EventArgs e)
        {
            try
            {
                Server s = (Server)Activator.GetObject(typeof(Server), "tcp://localhost:36433/distrrtgen");
                CG = s.Instance;
            }
            catch (SocketException ex)
            {
                MessageBox.Show("Unable to connect to local service. Can't save settings");
                return;
            }
            CG.Username = txtLocalUsername.Text;
            CG.Password = txtLocalPassword.Text;
            CG.MaxProcessorsToUse = (int)LocalMaxProcsToUse.Value;
            CG.AcceptNewParts = cbLocalAcceptNew.Checked;
            CG.UploadParts = cbLocalUpload.Checked;
            try
            {
                DateTime Start = Convert.ToDateTime(txtLocalUploadStart.Text);
                CG.UploadStartTime = Start;
            }
            catch
            {
                MessageBox.Show("Invalid time format in Upload Start");
            }
            try
            {
                DateTime End = Convert.ToDateTime(txtLocalUploadEnd.Text);
                CG.UploadEndTime = End;
            }
            catch
            {
                MessageBox.Show("Invalid time format in Upload End");
            }
            try
            {
                CG.WorkStartTime = Convert.ToDateTime(txtLocalWorkStart.Text);
            }
            catch
            {
                MessageBox.Show("Invalid time format in Work Start");
            }
            try
            {
                CG.WorkEndTime = Convert.ToDateTime(txtLocalWorkEnd.Text);
            }
            catch
            {
                MessageBox.Show("Invalid time format in Work End");
            }
            CG.EnablePublicHashCracking = cbLocalEnablePublicHashCracking.Checked;
            CG.EventLogThreshold = GetLoggerLevelFromIndex(evtLogThreshold.SelectedIndex);
//            if (!CG.IsRunning)
  //              CG.AsyncStart();
        }

        private void btnAddComputer_Click(object sender, EventArgs e)
        {
            AddComputer frm = new AddComputer();
            if (frm.ShowDialog() == DialogResult.OK)
            {
                if (frm.txtComputername.Text != "")
                {
                    Computer cmp = new Computer();
                    cmp.Hostname = frm.txtComputername.Text;
                    if (frm.cbCredentials.Checked == false)
                    {
                        cmp.Credentials.Username = frm.txtUsername.Text;
                        cmp.Credentials.Password = frm.txtPassword.Text;
                        cmp.Credentials.Domain = frm.txtDomain.Text;
                    }
                    _MachineList.Add(cmp);
                }
            }
        }

        private void btnRemoteSaveSettings_Click(object sender, EventArgs e)
        {
            int num = lvComputerList.SelectedItems.Count;
            for (int i = 0; i < num; i++)
            {
                Computer Machine = _MachineList.Get(lvComputerList.SelectedItems[i].SubItems[0].Text);
                Dictionary<string, Object> props = new Dictionary<string, Object>();
                props.Clear();
                props["name"] = "tcp";
                props["protectionLevel"] = System.Net.Security.ProtectionLevel.EncryptAndSign;
                props["secure"] = true;
                props["domain"] = Machine.Credentials.Domain;
                props["username"] = Machine.Credentials.Username;
                props["password"] = Machine.Credentials.Password;
                TcpClientChannel tcp = new TcpClientChannel(props, new BinaryClientFormatterSinkProvider());
                ChannelServices.UnregisterChannel(ChannelServices.RegisteredChannels[0]);
                ChannelServices.RegisterChannel(tcp, true);
                Server s = (Server)Activator.GetObject(typeof(Server), "tcp://" + Machine.Hostname + ":36433/distrrtgen");
                ChainGenerator _RemoteCG = s.Instance;

                if (_RemoteCG == null)
                    continue;

                _RemoteCG.Username = txtRemoteUsername.Text;
                _RemoteCG.Password = txtRemotePassword.Text;
                if (txtRemoteMaxCPU.Enabled) // Only update this if its enabled (All machines have same amount of CPU's)
                    _RemoteCG.MaxProcessorsToUse = (int)txtRemoteMaxCPU.Value;
                if (cbRemoteAcceptParts.CheckState != CheckState.Indeterminate)
                    _RemoteCG.AcceptNewParts = cbRemoteAcceptParts.Checked;
                if (cbRemoteUploadParts.CheckState != CheckState.Indeterminate)
                    _RemoteCG.UploadParts = cbRemoteUploadParts.Checked;
                if (cbRemotePublicHashCracking.CheckState != CheckState.Indeterminate)
                    _RemoteCG.EnablePublicHashCracking = cbRemotePublicHashCracking.Checked;
                try
                {
                    DateTime Start = Convert.ToDateTime(txtRemoteUploadStart.Text);
                    _RemoteCG.UploadStartTime = Start;
                }
                catch
                {
                    MessageBox.Show("Invalid time format in Upload Start");
                }
                try
                {
                    DateTime End = Convert.ToDateTime(txtRemoteUploadEnd.Text);
                    _RemoteCG.UploadEndTime = End;
                }
                catch
                {
                    MessageBox.Show("Invalid time format in Upload End");
                }
                try
                {
                    _RemoteCG.WorkStartTime = Convert.ToDateTime(txtRemoteWorkStart.Text);
                }
                catch
                {
                    MessageBox.Show("Invalid time format in Work Start");
                }
                try
                {
                    _RemoteCG.WorkEndTime = Convert.ToDateTime(txtRemoteWorkEnd.Text);
                }
                catch
                {
                    MessageBox.Show("Invalid time format in Work End");
                }

                _RemoteCG.EventLogThreshold = GetLoggerLevelFromIndex(cbRemoteEventThreshold.SelectedIndex);
//                if (!_RemoteCG.IsRunning)
  //                  _RemoteCG.AsyncStart();

            }

        }

        private void lvRemoteEventLog_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.lvRemoteEventLog.Sort();

        }

        private void lvLocalEventLog_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.lvLocalEventLog.Sort();

        }

        private void lvRemoteParts_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.lvRemoteParts.Sort();

        }

        private void lvComputerList_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.lvComputerList.Sort();
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            if (btnPause.Text == "Stop")
            {
                timerLocal.Enabled = false;
                serviceController1.Stop();
                btnPause.Text = "Start";
                Thread.Sleep(5000);
            }
            else
            {
                serviceController1.Start();
                btnPause.Text = "Stop";
                Thread.Sleep(5000);
                UpdateLocalView(false);
                timerLocal.Enabled = true;
            }
        }

        // Remote machine event log
        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string text = "";
            for (int i = 0; i < lvRemoteEventLog.SelectedItems.Count; i++)
            {
                text += lvRemoteEventLog.SelectedItems[i].SubItems[0].Text + "\t" +
                    lvRemoteEventLog.SelectedItems[i].SubItems[1].Text + "\t" +
                    lvRemoteEventLog.SelectedItems[i].SubItems[2].Text + "\t" +
                    lvRemoteEventLog.SelectedItems[i].SubItems[3].Text + "\r\n";
            }
            Clipboard.SetText(text);
        }

        // Local machine event log
        private void copyToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            string text = "";
            for (int i = 0; i < lvLocalEventLog.SelectedItems.Count; i++)
            {
                text += lvLocalEventLog.SelectedItems[i].SubItems[0].Text + "\t" +
                    lvLocalEventLog.SelectedItems[i].SubItems[1].Text + "\t" +
                    lvLocalEventLog.SelectedItems[i].SubItems[2].Text + "\r\n";
            }
            Clipboard.SetText(text);
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            if (Properties.Settings.Default.FirstTime == 1)
            {
                Welcome wel = new Welcome();
                wel.ShowDialog();
                if (wel.cbNeverShow.Checked == true)
                {
                    Properties.Settings.Default.FirstTime = 0;
                    Properties.Settings.Default.Save();
                }
            }
//            serviceController1.MachineName = "localhost";
            serviceController1.ServiceName = "DistrRTgen Service";
            if (serviceController1.Status != System.ServiceProcess.ServiceControllerStatus.StartPending && serviceController1.Status != System.ServiceProcess.ServiceControllerStatus.Running)
            {
                btnPause.Text = "Start";
            }
            else btnPause.Text = "Stop";
            //MessageBox.Show(serviceController1.Status.ToString());
        }

        private void lvComputerList_DoubleClick(object sender, EventArgs e)
        {
            UpdateRemoteView();
        }




    }
}